{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"35%\" align=\"right\" border=\"0\"><br><br><br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Listed Volatility and Variance Derivatives\n",
    "\n",
    "**Wiley Finance (2017)**\n",
    "\n",
    "Dr. Yves J. Hilpisch | The Python Quants GmbH\n",
    "\n",
    "http://tpq.io | [@dyjh](http://twitter.com/dyjh) | http://books.tpq.io\n",
    "\n",
    "<img src=\"http://hilpisch.com/../images/lvvd_cover.png\" alt=\"Derivatives Analytics with Python\" width=\"30%\" align=\"left\" border=\"0\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data Analysis and Strategies"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This chapter is about the analysis of data and investment strategies related to the EURO STOXX 50 and VSTOXX indexes. It uses public data sources (\"open data\") and draws heavily on the capabilities of the Python library pandas for data analytics.\n",
    "\n",
    "The chapter has two major goals. First, it reproduces the stylized fact that stock indexes and volatility indexes in general are *negatively correlated*. This suggests that (products based on) volatility indexes are a means to hedge market risk resulting from stock indexes. The question, however, is how to best exploit the negative correlation in asset allocation terms. Therefore, the second goal is to illustrate the benefits for equity investors resulting from *constant proportion investment strategies* involving a volatility index like the  VSTOXX. For simplicity, the respective analysis assumes that a direct investment in the VSTOXX is possible. This replicates results as found, for example, in the study by Guobuzaite and Martellini (2012)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Retrieving Base Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This section shows how to retrieve and store historical daily closing data for the EURO STOXX 50 index and the VSTOXX volatility index. We mainly work with pandas in the following."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### EURO STOXX 50 Data "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, the retrieval of data for the EUROSTOXX index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'https://hilpisch.com/lvvd_eikon_eod_data.csv'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.read_csv(url, index_col=0, parse_dates=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us inspect the first few rows of the ``DataFrame`` object. Given the raw data from above, we seem to have done everything right."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The single time series start in 2010 and go to November 2020."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before proceeding to the corresponding procedure for the VSTOXX data, the following visualizes the historical closing values for the EURO STOXX 50 index, i.e. for symbol `.STOXX50E`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from pylab import mpl, plt\n",
    "plt.style.use('seaborn')\n",
    "mpl.rcParams['font.family'] = 'serif'  # set serif font\n",
    "data['.STOXX50E'].plot(grid=True, figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Historical EURO STOXX 50 index levels."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### VSTOXX Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Second, visualizing the data from the same source as before for the VSTOXX index. The following figure visualizes the times series data for the main volatility index with symbol `.V2TX`. Inspection of the the figure reveals that the volatility index increases and even spikes when there are crises in the markets &mdash; which is best seen in the beginning of 2020."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data['.V2TX'].plot(grid=True, figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Historical VSTOXX index levels."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Data Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As illustrated in the appendix about _Introduction to Python_, pandas provides a wealth of options to analyze data stored in ``DataFrame`` objects. A sometimes helpful method is ``describe()`` which provides selected meta statistics for the single data sub-sets stored in ``DataFrame`` columns."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sub-plots of multiple data sub-sets are easily generated with pandas. The result of the following plotting code is found in the following figure. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data[['.STOXX50E', '.V2TX']].plot(subplots=True,  # generate sub-plots per column\n",
    "        figsize=(10, 6),  # sizing of the figure\n",
    "        color='blue');  # color to plot the data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Historical EURO STOXX 50 and VSTOXX index levels."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly, you can visualize the absolute differences (over time) by using the ``diff()`` method and plotting them as a histogram (see the following the figure). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data[['.STOXX50E', '.V2TX']].diff().hist(figsize=(10, 6),  # figure sizing\n",
    "                 color='blue',  # color for the plotted data\n",
    "                 bins=100);  # number of bins to be used"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Histograms of historical absolute daily differences of EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In similar spirit, we can calculate the relative or percent changes for the time series data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data.pct_change().iloc[-10:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The code to visualize this kind of result is the same as before (see the following figure)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data[['.STOXX50E', '.V2TX']].pct_change().hist(figsize=(10, 6),\n",
    "                       color='blue', \n",
    "                       bins=100);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Histograms of historical percentage changes of EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The majority of statistical analysis approaches relies on (log) returns and not on absolute time series data. The next few lines of code calculate the log returns for the two time series and stores them in yet another `DataFrame` object, called `log_rets`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "## fully vectorized calculation of log returns\n",
    "log_rets = np.log(data / data.shift(1))\n",
    "log_rets.iloc[:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following figure visualizes the log returns times series for both the EURO STOXX 50 and VSTOXX indexes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "log_rets[['.STOXX50E', '.V2TX']].plot(subplots=True,\n",
    "              figsize=(10, 6),\n",
    "              color='blue',\n",
    "              grid=True);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Log returns of EURO STOXX 50 and VSTOXX over time."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Correlation Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Equipped with the log returns, a thorough investigation of the correlation between the EURO STOXX 50 and VSTOXX indexes is straightforward. For example, pandas provides the ``corr()`` method to calculate correlations between time series data stored in different ``DataFrame`` columns."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "log_rets.corr()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similar results are obtained by calculating the correlation of the data stored in one pandas `Series` object with another data set in another `Series` object. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "log_rets['.STOXX50E'].corr(log_rets['.V2TX'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``plot()`` method of pandas ``DataFrame`` objects knows different types of plots. For example, scatter plots are helpful to visualize return data of two different time series (see the following figure)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "## plot log returns as scatter plot\n",
    "log_rets.plot(x='.STOXX50E', y='.V2TX',\n",
    "              kind='scatter', figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Scatter plot of log returns of EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following figure adds the time dimension to the data through coloring to illustrate the relation between the two time series over time (during different \"regimes\")."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "log_rets = log_rets.dropna() # delete NaN values\n",
    "plt.set_cmap('coolwarm');  # set color map\n",
    "mpl_dates = mpl.dates.date2num(log_rets.index.to_pydatetime())  # conversion\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.scatter(log_rets['.STOXX50E'], log_rets['.V2TX'],\n",
    "            c=mpl_dates, marker='o', alpha=0.75)  # the actual plot\n",
    "plt.xlabel('.STOXX50E')\n",
    "plt.ylabel('.V2TX')\n",
    "plt.colorbar(ticks=mpl.dates.DayLocator(interval=250),  # adding bar\n",
    "        format=mpl.dates.DateFormatter('%d %b %y')); "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Scatter plot of log returns of EURO STOXX 50 and VSTOXX with dates."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although the negative correlation between the two indexes is almost evident from the previous two figures, let us formally calculate and represent the negative correlation by a linear regression line.The following figure adds such a regression line to the raw log returns in the scatter plot. Negative correlation translates into a negative slope of the regression line."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "## conduct linear regression\n",
    "p = np.polyfit(log_rets['.STOXX50E'].values,\n",
    "               log_rets['.V2TX'].values,\n",
    "               deg=1)  # the regression\n",
    "log_rets.plot(x='.STOXX50E', y='.V2TX',\n",
    "              kind='scatter', figsize=(10, 6));  # the actual plotting\n",
    "## plot the regression line\n",
    "plt.plot(log_rets['.STOXX50E'], np.polyval(p, log_rets['.STOXX50E']),\n",
    "         'r');  # adding the regression line"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Scatter plot of log returns of EURO STOXX 50 and VSTOXX with regression line."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The seaborn plotting library is specifically developed with statistical applications in mind. It therefore provides multiple useful, high level plotting capabilities. One of the them is the ``jointplot()`` function. The result of applying this function to the log return data is displayed in the following figure. For sure the richest and most insightful presentation so far for our purposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "sns.jointplot(x=log_rets['.STOXX50E'], y=log_rets['.V2TX'], \n",
    "              kind='reg', height=7);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Scatter plot of log returns of EURO STOXX 50 and VSTOXX with regression line and histograms."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The final analysis in this section considers correlation *over time*. To this end, pandas provides the ``rolling()`` method which allows, among otherts, the vectorized calculation of correlation for moving time windows via ``corr()``. We chose a window size of 252 trading days which represents roughly one year."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['CORR'] = log_rets['.STOXX50E'].rolling(\n",
    "                window=252).corr(log_rets['.V2TX'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following figure shows the rolling correlation data and illustrates well that correlation fluctuates for different yearly windows but that it is negative for any chosen yearly window."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "to_plot = data.dropna()  # drop NaN values\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(data.index, data.CORR)\n",
    "plt.ylabel('rolling yearly correlation');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Rolling yearly correlation of EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Constant Proportion Investment Strategies"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One way to make use of the fact that the VSTOXX index is negatively correlated with the EURO STOXX 50 index is to implement a *constant proportion investment strategy*. Respective results are found, for example, in the study by Guobuzaite and Martellini (2012). Basically, a constant (dollar) proportion investment strategy keeps the proportion of money invested in securities of a portfolio over time constant by dynamic re-balancings given the movements in the prices of the single securities.\n",
    "\n",
    "In the example of this section, we assume that direct investments both in the EURO STOXX 50 and the VSTOXX indexes are possible and that no transaction costs apply. Although this might not be realistic, it simplifies the anaylsis and illustrates the basic idea pretty well.\n",
    "\n",
    "To begin with, let us adjust the origingal data sets for the EURO STOXX 50 and VSTOXX indexes by mainly normalizing both time series to starting values of 100."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "del data['CORR']  # delete correlation data\n",
    "data = data.dropna()  # drop NaN values\n",
    "data = data / data.iloc[0] * 100  # normalization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we analyze a typical *passive investment strategy* allocating 30% of a portfolio to the VSTOXX index and the remaining 70% to the EURO STOXX 50."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "invest = 100  # initial investment\n",
    "cratio = 0.3  # VSTOXX ratio in the beginning\n",
    "## number of EURO STOXX (fictional) securities\n",
    "data['Equity'] = (1 - cratio) * invest / data['.STOXX50E'][0]\n",
    "## number of VSTOXX (fictional) securities\n",
    "data['Volatility'] = cratio * invest / data['.V2TX'][0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In vectorized fashion, we calculate next the absolute values of such a portfolio over time, i.e. as a time series."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['Passive'] = (data['Equity'] * data['.STOXX50E']\n",
    "                + data['Volatility'] * data['.V2TX'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following figure illustrates the performance of this particular passive investment strategy in comparison to a passive strategy purely investing in the EURO STOXX 50 index. In times of crises, for example at the beginning of 2020, the strategy peforms better. However, over the whole period there is hardly a difference in the end result.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data[['.STOXX50E', 'Passive']].plot(figsize=(10, 6), style=['--', '-']);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Passive investment strategy (hypothetical) with EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Second, the *active constant proportion investment strategy*, which keeps the dollar proportion invested in the VSTOXX index constant at 30% *over time* through daily re-balancings of the portfolio. In this case, the single calculations are done step-by-step through looping over the single historical trading dates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(1, len(data)):  # daily re-balancing\n",
    "    evalue = data['Equity'].iloc[i - 1] * data['.STOXX50E'].iloc[i]\n",
    "    vvalue = data['Volatility'].iloc[i - 1] * data['.V2TX'].iloc[i]\n",
    "    tvalue = evalue + vvalue  # total wealth  \n",
    "    data['Equity'].iloc[i] = (1 - cratio) * tvalue / data['.STOXX50E'].iloc[i] \n",
    "    data['Volatility'].iloc[i] = cratio * tvalue / data['.V2TX'].iloc[i] "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Based on the results, we calculate the  absolute performance of this active strategy as before. Over the first few trading days no major performance differences arise."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data['Active'] = (data['Equity'] * data['.STOXX50E']\n",
    "                + data['Volatility'] * data['.V2TX'])\n",
    "np.round(data.head(), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Over the whole time period, however, the active strategy &mdash; showing a 600+ percent gain &mdash; significantly outperforms the passive one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "np.round(data.tail(), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us briefly verify whether the above implementation indeed yields constant proportions for the two (fictional) securities in the portfolio."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "(data['Volatility'] * data['.V2TX'] / data['Active'])[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "(data['Equity'] * data['.STOXX50E'] / data['Active'])[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Being assured that we indeed have implemented a constant proportion trading strategy, have a look at the following figure which impressively illustrates the outperformance of the active approach over a passive investment in the stock index itself. However, keep in mind that all this rests on a number of simplifying assumptions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "data[['.STOXX50E', 'Active']].plot(figsize=(10, 6), style=['--', '-']);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"font-family: monospace;\">Active, constant proportion investment strategy (hypothetical) with EURO STOXX 50 and VSTOXX."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The assumption of 30% invested in the VSTOXX index might seem a bit ad hoc. Therefore, the following derives the optimal allocation for the given time period and data sets by a brute force approach. First, we clean up the ``DataFrame`` object to reduce it again to the original time series data for the two indexes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## re-initialize DataFrame\n",
    "data = data[['.STOXX50E', '.V2TX']]\n",
    "data.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The function below calculates the performance of a constant proportion investment strategy for different VSTOXX dollar proportions and different starting and ending dates (both defaulting to the data sets' start and end dates)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from copy import deepcopy\n",
    "def vstoxx_strategy(cratio, start=data.index[0], end=data.index[-1]):\n",
    "    base = deepcopy(data[(data.index >= start) & (data.index <= end)])\n",
    "    invest = 100  # initial invest\n",
    "    base['Equity'] = (1 - cratio) * invest / base['.STOXX50E'].iloc[0]\n",
    "    base['Volatility'] = cratio * invest / base['.V2TX'].iloc[0]\n",
    "    for i in range(1, len(base)):  # daily re-balancing\n",
    "        evalue = base['Equity'].iloc[i - 1] * base['.STOXX50E'].iloc[i]\n",
    "        vvalue = base['Volatility'].iloc[i - 1] * base['.V2TX'].iloc[i]\n",
    "        tvalue = evalue + vvalue\n",
    "        base['Equity'].iloc[i] = (1 - cratio) * tvalue / base['.STOXX50E'].iloc[i]\n",
    "        base['Volatility'].iloc[i] = cratio * tvalue / base['.V2TX'].iloc[i]\n",
    "    base['Active'] = (base['Equity'] * base['.STOXX50E']\n",
    "                + base['Volatility'] * base['.V2TX'])  # wealth position\n",
    "    print('A con. VSTOXX ratio of %.2f yields a net perform. of %6.1f%%.' \\\n",
    "            % (cratio, (base['Active'].iloc[-1] / base['Active'].iloc[0] - 1) * 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Equipped with this function, let us calculate the net perfomance for a VSTOXX dollar ratio of 30% as before."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "vstoxx_strategy(0.3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We do the same for 40% which obviously yields an even better result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "vstoxx_strategy(0.4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Applying an approach which is a bit more systematic, we get the following results for different constant dollar proportion assumptions. Over the whole period for which data is available a 50%:50% investment strategy seems to be optimal with a net performance of more than 900%."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "for cratio in np.arange(0, 1.01, 0.1):\n",
    "    vstoxx_strategy(cratio)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us implement the same analysis for the time period beginning in January 2017 and ending with the second quarter of 2020. In this case, a constant dollar proportion invested in the VSTOXX of about 60% seems optimal and yields a net performance of about 220%."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "for cratio in np.arange(0, 1.01, 0.1):\n",
    "    vstoxx_strategy(cratio, start='2017-1-1', end='2020-7-1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "for cratio in np.arange(0, 1.01, 0.1):\n",
    "    vstoxx_strategy(cratio, start='2019-7-1', end='2020-10-31')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This chapter is about the retrieval and analysis of EURO STOXX 50 and VSTOXX historical data. It shows how to use Python and pandas to retrieve historical data sets with pandas. It also shows how to implement Python code to replicate central stylized facts about stock and volatility indexes, namely their highly negative correlation and the benefits of constant (dollar) proportion investment strategies involving (products based on) equity and volatility indexes."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"35%\" align=\"right\" border=\"0\"><br>\n",
    "\n",
    "<a href=\"http://tpq.io\" target=\"_blank\">http://tpq.io</a> | <a href=\"http://twitter.com/dyjh\" target=\"_blank\">@dyjh</a> | <a href=\"mailto:team@tpq.io\">team@tpq.io</a>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
